package com.mccken.eshop.common.exception;

import java.util.Iterator;
import java.util.List;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.springframework.core.annotation.Order;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import cn.hutool.core.util.StrUtil;
import com.mccken.eshop.common.code.JsonResult;
import lombok.extern.slf4j.Slf4j;

/**
 * 默认的controller全局异常处理增强组件
 * 
 * @program: mccken-collect
 * @description:
 * @author: mccken
 * @create: 2022-08-25 23:12
 **/
@Slf4j
@Order
@RestControllerAdvice // mccken_mark
public class GlobalExceptionHandler {
	
	// ======== 系统级别未知异常 ===========
	@ExceptionHandler(value = Exception.class)
	public JsonResult<Object> handle(Exception e) {
		log.error("[ 系统位置错误 ]", e);
		return JsonResult.buildError(CommonErrorCodeEnum.SYSTEM_UNKNOWN_ERROR);
	}

	// ======== 客户端异常 ===========

	/**
	 * 1001 HTTP请求方法类型错误
	 * @param e
	 * @return
	 */
	@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
	public JsonResult<Object> handle(HttpRequestMethodNotSupportedException e) {
		log.error("[客户端HTTP请求方法错误]", e);
		return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_HTTP_METHOD_ERROR);
	}

	/**
	 * 1002 客户端请求体参数校验不通过
	 */
	@ExceptionHandler(value = MethodArgumentNotValidException.class)
	public JsonResult<Object> handle(MethodArgumentNotValidException e) {
		log.error("[客户端请求体参数校验不通过]", e);
		String errorMsg = this.handle(e.getBindingResult().getFieldErrors());
		return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_REQUEST_BODY_CHECK_ERROR.getErrorCode(), errorMsg);
	}
	
	private String handle(List<FieldError> fieldErrors) {
		StringBuilder sb = new StringBuilder();
		for (FieldError fieldError : fieldErrors) {
			sb.append(fieldError.getField());
			sb.append("=[");
			sb.append(fieldError.getDefaultMessage());
			sb.append("] ");
		}
		return sb.toString();
	}

	/**
	 * 1005 客户端请求参数校验不通过
	 */
	@ExceptionHandler(value = ConstraintViolationException.class)
	public JsonResult<Object> handle(ConstraintViolationException e) {
		log.error("[客户端请求参数校验不通过]",e);
		Iterator<ConstraintViolation<?>> it = e.getConstraintViolations().iterator();
		String errorMsg = null;
		if (it.hasNext()) {
			errorMsg = it.next().getMessage();
		}
		if (StrUtil.isNotBlank(errorMsg)) {
			return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_REQUEST_PARAM_CHECK_ERROR.getErrorCode(), errorMsg);
		}

		return JsonResult.buildError(CommonErrorCodeEnum.CLIENT_REQUEST_PARAM_CHECK_ERROR);
	}

	// TODO 还有一些异常的处理没有写

	// ======== 系统级别未知异常 ===========

	/**
	 * 2001 业务方法参数检查不通过
	 * @param e
	 * @return
	 */
	@ExceptionHandler(value = IllegalArgumentException.class)
	public JsonResult<Object> handle(IllegalArgumentException e) {
		log.error("[业务方法参数检查不通过]", e); 
		return JsonResult.buildError(CommonErrorCodeEnum.SERVER_ILLEGAL_ARGUMENT_ERROR);
	}
	
	
	/**
	 * 系统自定义业务异常
	 */
	@ExceptionHandler(value = BaseBizException.class)
	public JsonResult<Object> handle(BaseBizException e) {
		log.error("[业务异常]", e);
		return JsonResult.buildError(e.getErrorCode(), e.getErrorMsg());
	}
	
}




















